#include "amr_main.h"
#include "Individual.h"
#include <iostream>

using namespace std;

// Constructor for CIndividual class
CIndividual::CIndividual(int NumLoci, int FitnessFunction)
{
	// Test whether number of loci is greater than zero
	m_NumLoci = NumLoci;
	if (m_NumLoci < 1)
	{
		cerr << "AMR Run-time error:" << endl;
		cerr << "NumLoci is less than one." << endl;
		cerr << "Exiting program" << endl;
		exit (8);
	}
	else 
	{
		m_Genotype1 = new int [NumLoci];
		m_Genotype2 = new int [NumLoci];
		m_Gamete = new int [NumLoci];
		if (m_Genotype1 == 0 || m_Genotype2 == 0 || m_Gamete ==  0)
		{
			cerr << "AMR Run-time error:" << endl;
			cerr << "Could not allocate memory for genotypes/gamete." << endl;
			cerr << "Exiting program" << endl;
			exit (8);
		}
	}

	// Test whether the fitness function is valid
	m_FitnessFunction = FitnessFunction;
	if (m_FitnessFunction < LINEAR || m_FitnessFunction > ASYMPTOTIC)
	{
		cerr << "AMR Run-time error:" << endl;
		cerr << "Invalid fitness function." << endl;
		cerr << "Exiting program" << endl;
		exit (8);
	}

	// Assign ancestral state to all loci in the genotype
	for (int locus=0; locus < m_NumLoci; locus++)
	{
		m_Genotype1[locus] = ANC;
		m_Genotype2[locus] = MUT;
	}
}

// CIndividual deconstructor
CIndividual::~CIndividual(void)
{
	delete [] m_Genotype1;
	delete [] m_Genotype2;
}

// Make gamete with free recombination
void CIndividual::MakeGamete(MyEngine Engine)
{
	MyUniform UniformDist(0,1);

	for (int locus=0; locus < m_NumLoci; locus++)
	{
		if (UniformDist(Engine) < 0.5)
			m_Gamete[locus] = m_Genotype1[locus];
		else
			m_Gamete[locus] = m_Genotype2[locus];
	}
}

// Print the gamete of an individual
void CIndividual::PrintGamete(void)
{
	cout << "Gamete:" << endl;
	for (int locus=0; locus < m_NumLoci; locus++)
		cout << m_Gamete[locus];
	cout << endl;
}

// Prints the genotype of an individual to the stdout
void CIndividual::PrintGenotype(void)
{
	int locus;

	cout << "Genotype 1:" << endl;
	for (locus=0; locus < m_NumLoci; locus++)
		cout << m_Genotype1[locus];
	cout << endl << "Genotype 2:" << endl;
	for (locus=0; locus < m_NumLoci; locus++)
		cout << m_Genotype2[locus];
	cout << endl;
}

// Calculates the fitness of an individual
void CIndividual::CalculateFitness(int FitnessFunction)
{
	switch (FitnessFunction)
	{
		case LINEAR:
			m_Fitness = 1.0;
			break;
		case THRESHOLD:
			m_Fitness = 2.0;
			break;
		case ASYMPTOTIC:
			m_Fitness = 3.0;
			break;
	}
}

// Prints the fitness of an individual
void CIndividual::PrintFitness(void)
{
	cout << "Fitness: " << m_Fitness << endl;
}